package rlyy.framework.core.maping;

import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * url和mapping映射关系
 *
 * @author yuanqinglong
 * @since 2020/11/26 11:32
 */
@Component
public class RequestHandlerMapping implements ApplicationContextAware {

    static final Logger logger = LoggerFactory.getLogger(RequestHandlerMapping.class);

    /**
     * 请求路径和执行方法映射关系
     */
    private final Map<String, HandlerMethod> handlerMethods = new ConcurrentHashMap<>(128);
    /**
     * API统计
     */
    private final Map<String, AtomicInteger> apiCount = new ConcurrentHashMap<>(128);

    @Autowired
    private RequestMappingInfoHandlerMapping requestMappingInfoHandlerMapping;


    @Override
    public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
        logger.info("Start set mapping relation");
        requestMappingInfoHandlerMapping.getHandlerMethods().forEach((requestMappingInfo, handlerMethod) ->
                requestMappingInfo.getPatternsCondition().getPatterns().forEach(uri -> {
                            String convertUri = convertUri(uri);
                            handlerMethods.put(convertUri, handlerMethod.createWithResolvedBean());
                            apiCount.put(convertUri, new AtomicInteger());
                        }
                ));
        logger.info("Set mapping relation completed");
    }

    /**
     * 通过url获取处理请求方法和实例
     *
     * @param url url
     * @return ReflexEntity
     */
    public HandlerMethod getHandlerMapping(final String url) {
        return handlerMethods.get(url);
    }

    /**
     * 判断url是否有映射关系
     *
     * @param url url
     * @return boolean or false
     */
    public boolean containsUrlMapping(final String url) {
        return handlerMethods.containsKey(url);
    }

    /**
     * @param url url
     * @return boolean or false
     */
    public boolean containsUrlApiCount(final String url) {
        return apiCount.containsKey(url);
    }

    /**
     * 获取api请求次数
     *
     * @return apiCount
     */
    public AtomicInteger getApiCount(final String url) {
        return apiCount.get(url);
    }

    /**
     * api请求自增
     *
     * @return apiCount
     */
    public int apiIncrementAndGet(final String url) {
        return apiCount.get(url).incrementAndGet();
    }

    /**
     * api请求自增减
     *
     * @return apiCount
     */
    public int apiDecrementAndGet(final String url) {
        return this.containsUrlApiCount(url) ? apiCount.get(url).decrementAndGet() : 0;
    }


    public static String convertUri(String uri) {
        List<String> uriList = Splitter.on("/").splitToList(uri);
        uriList = uriList.stream().filter(StringUtils::hasLength).collect(Collectors.toList());
        return Joiner.on("_").join(uriList);
    }

}

